package com.littlerpc.protocol.net.common;

import com.littlerpc.protocol.exception.RpcException;
import lombok.Getter;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

/**
 *
 * @author ChengPeng
 * @date 2017/6/14
 */
public class RpcFuture<T> {

    private Object lock = new Object();
    private T t = null;

    private FutureLock futureLock = new FutureLock();

    @Getter
    private List<RpcFutureListener> listeners = new ArrayList<>();

    public RpcFuture addListener(RpcFutureListener l) {
        listeners.add(l);
        return  this;
    }


    protected RpcFuture() {
    }

    public void setResult(T t) {
        this.t = t;
    }

    public T get() {

        futureLock.acquire(0);

        if(t == null) {
            throw new RpcException("Rpc 获取值失败！");
        }

        return t;
    }



    public T get(long timeout) throws Exception{

        synchronized (lock){
            try {
                lock.wait(timeout);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        if(t == null) {
            throw new RpcException("Rpc 获取值失败！");
        }

        return t;

    }


    public void done() {
        futureLock.release(1);
    }

    class FutureLock extends AbstractQueuedSynchronizer {

        @Override
        /**
         * 释放锁，将状态设置成1
         */
        protected boolean tryRelease(int arg) {
            if(getState() == 0) {
                //将状态设置成1
                return compareAndSetState(0,1);
            }
            return false;
        }

        @Override
        /**
         * 获取锁
         * 将状态设置成0
         */
        protected boolean tryAcquire(int arg) {
            return compareAndSetState(1,0);
        }
    }



}
